<!DOCTYPE html>
<html>
<head>
  <meta charset="utf-8">
  
  
  <title>sdtggd的博客</title>
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta property="og:type" content="website">
<meta property="og:title" content="sdtggd的博客">
<meta property="og:url" content="https://lhaik.gitcode.host/index.html">
<meta property="og:site_name" content="sdtggd的博客">
<meta property="og:locale" content="zh_CN">
<meta property="article:author" content="lhaik">
<meta name="twitter:card" content="summary">
  
    <link rel="alternate" href="/atom.xml" title="sdtggd的博客" type="application/atom+xml">
  
  
    <link rel="shortcut icon" href="/favicon.png">
  
  
  
<link rel="stylesheet" href="/css/style.css">

  
    
<link rel="stylesheet" href="/fancybox/jquery.fancybox.min.css">

  
  
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/fork-awesome@1.2.0/css/fork-awesome.min.css">

<meta name="generator" content="Hexo 7.3.0"></head>

<body>
  <div id="container">
    <div id="wrap">
      <header id="header">
  <div id="banner"></div>
  <div id="header-outer" class="outer">
    <div id="header-title" class="inner">
      <h1 id="logo-wrap">
        <a href="/" id="logo">sdtggd的博客</a>
      </h1>
      
        <h2 id="subtitle-wrap">
          <a href="/" id="subtitle">学习记录</a>
        </h2>
      
    </div>
    <div id="header-inner" class="inner">
      <nav id="main-nav">
        <a id="main-nav-toggle" class="nav-icon"><span class="fa fa-bars"></span></a>
        
          <a class="main-nav-link" href="/">Home</a>
        
          <a class="main-nav-link" href="/archives">Archives</a>
        
      </nav>
      <nav id="sub-nav">
        
        
          <a class="nav-icon" href="/atom.xml" title="RSS 订阅"><span class="fa fa-rss"></span></a>
        
        <a class="nav-icon nav-search-btn" title="搜索"><span class="fa fa-search"></span></a>
      </nav>
      <div id="search-form-wrap">
        <form action="//google.com/search" method="get" accept-charset="UTF-8" class="search-form"><input type="search" name="q" class="search-form-input" placeholder="搜索"><button type="submit" class="search-form-submit">&#xF002;</button><input type="hidden" name="sitesearch" value="https://lhaik.gitcode.host"></form>
      </div>
    </div>
  </div>
</header>

      <div class="outer">
        <section id="main">
  
    <article id="post-一些最近写比赛项目的心得" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/2025/06/09/%E4%B8%80%E4%BA%9B%E6%9C%80%E8%BF%91%E5%86%99%E6%AF%94%E8%B5%9B%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%BF%83%E5%BE%97/" class="article-date">
  <time class="dt-published" datetime="2025-06-09T12:20:29.000Z" itemprop="datePublished">2025-06-09</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/2025/06/09/%E4%B8%80%E4%BA%9B%E6%9C%80%E8%BF%91%E5%86%99%E6%AF%94%E8%B5%9B%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%BF%83%E5%BE%97/">一些最近写比赛项目的心得</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <pre><code>从24年10月份开始，我就开始在邬老师的指导下写物联网大赛的比赛项目，主要就是将前端、后端、数据库给串通起来，前端用的是vue框架，后端用的是nodejs加koa框架加websocket协议、http协议、mqtt协议，数据库有的就是mysql，现在让我说一下遇到的一些问题以及怎么解决的吧。
首先这个项目既然是为了物联网大赛，肯定是要与物理层进行通信的，大体就是物理层传数据，应用层接受数据并传控制底层设备的指令，很普遍，但有意思的是，最开始我们都是使用mqtt协议进行传输的，很简单，就调几个api就行，但因为25年物联网大赛的更新，要求我们跟上时代的步伐，项目要与大模型进行集成，就是说服务器要接入大模型，用于识别底层传的视频，并要求我们用http协议，好了，现在讲遇到的一些问题：
1.心跳问题：
    心跳反应是很常见的判断设备是否在线的方法，具体就是物理层要在特定时间向应用层发送一个心跳消息，那么应用层要设置一个定时器用来循环心跳检测，在定时器内又设置在几秒内如果未收到心跳消息则会判断设备掉线，然后我们需到的问题就是即便物理层一直在发送心跳，但应用层有时还是会判断设备掉线，这是因为在定时器时间间隔，如定时器是三秒一次，而判断的时间是2秒，那么就会存在一秒的间隔，这时候如果物理层的心跳也是在1秒以上的时间发送心跳，就会卡到这个间隔上，导致设备掉线，所以物理层就要把心跳设在1秒内发送

2.事件监听方法
    在项目要求实时更新数据，其实是很简单的事情就是通过ws来实现，但怎么将ws和http协议接受数据联系起来就是问题了，这时就要用到全局事件监听了，在nodejs中，我们可以通过events模块来实现，在events模块中，有一个EventEmitter类，这个类提供了一些方法，我们可以通过这个类来创建一个事件监听器，然后通过这个监听器来监听事件，当事件发生时，可以执行相应的回调函数。比如
    events.emit(&#39;update&#39;,&#123;
        type:&#39;sensor&#39;
    &#125;)这是暴露一个名为update的事件，然后在ws中就要监听这个事件，当出现事件的时候，就提醒前端进行数据更新
     events.on(&#39;update&#39;,(payload)=&gt;&#123;
        let type = payload.type
        if(type == &#39;error&#39;)&#123;
            ws.send(JSON.stringify(&#39;error&#39;))
        &#125;else if(type == &#39;sensor&#39;)&#123;
            ws.send(JSON.stringify(&#39;sensor&#39;))
        &#125;else&#123;
            ws.send(JSON.stringify(&#39;behavior&#39;))
        &#125;
    &#125;)

3.如何将不同的指令动态的渲染到页面上
    这真是当初难死我的地方，首先我们要根据指令的类型写好组件，然后在父组件上根据后端发过来的数据中的指令类型来动态渲染组件。
    getComponentName(direct) &#123;
        switch (direct.f_type) &#123;
        case &#39;1&#39;:
            return &#39;SwitchComponent&#39;;
        case &#39;2&#39;:
            return &#39;InputControl&#39;;
        case &#39;3&#39;:
            return &#39;SliderComponent&#39;;
        case &#39;4&#39;:
            return &#39;DateControl&#39;;
        case &#39;5&#39;:
            return &#39;RadioControl&#39;;
        case &#39;6&#39;:
            return &#39;DateRange&#39;;
        default:
            return &#39;div&#39;; // 默认渲染一个 div
        &#125;
    &#125;
    &lt;div class=&quot;content&quot;&gt;
        &lt;component v-for=&quot;direct in all_direct&quot; 
        :key=&quot;direct.order&quot; 
        :is=&quot;getComponentName(direct)&quot; 
        :direct=&quot;direct&quot; :d_no=&quot;null&quot; @sendDirect=&quot;sendDirect&quot;
        :style=&quot;&#39;margin-left:&#39; + 20 * direct.level + &#39;px;margin-top:10px;&#39;&quot;&gt;&lt;/component&gt;
    &lt;/div&gt;
    值得注意的是，在vue中如果key相同的话，那么组件会复用，不会重新渲染。所以在处理不同设备相同指令的时候，key值要取一个唯一值，不然指令不会刷新。然后还有在浏览器中ajax或是axios请求的次数是有限的，因为每次改变一个指令都要重新请求，请求次数过多就不再刷新了，所以我这里用的是ws

4.如何将表格中的地址改成能点击的超链接
    这里用到的是插槽
    &lt;el-table-column v-for=&quot;(p,index) in header1&quot; 
        :prop=&quot;p.prop&quot; 
        :key=&quot;index&quot;
        :label=&quot;p.label&quot;
        width=&quot;180&quot;
    &gt;
        &lt;template #default=&quot;scope&quot;&gt;//名字为default，scope为上下文
            &lt;a 
            v-if=&quot;p.label === &#39;视频地址 &#39;&quot; 
            :href=&quot;scope.row[p.prop]&quot; 
            target=&quot;_blank&quot;  // 允许打开新窗口
            rel=&quot;noopener noreferrer&quot;
            &gt;
                点击播放
            &lt;/a&gt;
            &lt;span v-else&gt;&#123;&#123; scope.row[p.prop] &#125;&#125;&lt;/span&gt;
        &lt;/template&gt;
    &lt;/el-table-column&gt;

暂时只想到这些，后续如果想到新的，会继续添加 
</code></pre>

      
    </div>
    <footer class="article-footer">
      <a data-url="https://lhaik.gitcode.host/2025/06/09/%E4%B8%80%E4%BA%9B%E6%9C%80%E8%BF%91%E5%86%99%E6%AF%94%E8%B5%9B%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%BF%83%E5%BE%97/" data-id="cmbqcgbjv0001nsg6cv6j0ayl" data-title="一些最近写比赛项目的心得" class="article-share-link"><span class="fa fa-share">分享</span></a>
      
      
      
    </footer>
  </div>
  
</article>



  
    <article id="post-koa2的学习" class="h-entry article article-type-post" itemprop="blogPost" itemscope itemtype="https://schema.org/BlogPosting">
  <div class="article-meta">
    <a href="/2025/06/06/koa2%E7%9A%84%E5%AD%A6%E4%B9%A0/" class="article-date">
  <time class="dt-published" datetime="2025-06-06T08:56:02.000Z" itemprop="datePublished">2025-06-06</time>
</a>
    
  </div>
  <div class="article-inner">
    
    
      <header class="article-header">
        
  
    <h1 itemprop="name">
      <a class="p-name article-title" href="/2025/06/06/koa2%E7%9A%84%E5%AD%A6%E4%B9%A0/">koa2的学习</a>
    </h1>
  

      </header>
    
    <div class="e-content article-entry" itemprop="articleBody">
      
        <h1 id="koa2的学习"><a href="#koa2的学习" class="headerlink" title="koa2的学习"></a>koa2的学习</h1><p>今天我们来学习koa2框架，我愿称它为进阶版的express,但它比起express又轻量很多</p>
<p>首先我们要使用koa2肯定是要安装的，通过 npm i koa 进行安装</p>
<h2 id="创建一个简单的服务器"><a href="#创建一个简单的服务器" class="headerlink" title="创建一个简单的服务器"></a>创建一个简单的服务器</h2><p>然后和express一样的，我们先启动一个简单的http服务器，创建一个文件夹，在终端输入 npm init -y 进行初始化，生成package.json文件，再创建一个index.js文件，开始写服务器</p>
<p><strong>import koa from ‘koa’</strong></p>
<p><strong>const app &#x3D; new koa()</strong></p>
<p><strong>app.use(async ctx &#x3D;&gt; {</strong></p>
<p>​    ctx.body &#x3D; ‘hello koa’</p>
<p><strong>})</strong></p>
<p><strong>app.listen(3000,()&#x3D;&gt;{</strong></p>
<p>​    console.log(‘服务器运行在 <a target="_blank" rel="noopener" href="http://localhost:3000/">http://localhost:3000</a>‘)</p>
<p><strong>})</strong></p>
<p>是不是很熟悉，这就是express中的样式啊，只是在express中的req，res换成了context上下文，更加方便，需要注意的是node默认是用commonJS语法的，但我这用了ES6的语法，是在packae.json文件中加了”type”:”module”这一句话</p>
<h2 id="koa的中间件"><a href="#koa的中间件" class="headerlink" title="koa的中间件"></a>koa的中间件</h2><p>koa中间件其实上面已经用到了，就是app.use()，是用来处理http请求与响应的函数</p>
<p><strong>app.use(async (ctx,next) &#x3D;&gt; {</strong></p>
<p>​    console.log(‘中间件1’)</p>
<p>​    next()</p>
<p>​    console.log(‘中间件1 结束’)</p>
<p><strong>})</strong></p>
<p><strong>app.use(async (ctx,next) &#x3D;&gt; {</strong></p>
<p>​    console.log(‘中间件2’)</p>
<p>​    next()</p>
<p>​    console.log(‘中间件2 结束’)</p>
<p><strong>})</strong></p>
<p><strong>app.use(async (ctx,next) &#x3D;&gt; {</strong></p>
<p>​    console.log(‘中间件3’)</p>
<p><strong>})</strong></p>
<p>在这里我用了三个中间件，它的执行顺序是从上到下，当遇到next()函数的时候会停止当前中间件，执行下一个中间件，然后再倒着执行，也就是执行顺序是1 2 3 2 1</p>
<h2 id="路由"><a href="#路由" class="headerlink" title="路由"></a>路由</h2><p>又是路由，当涉及到网址相关部分的时候总是会避不开这个东西，接下来我们来学学koa中的路由，首先要用路由，先安装 npm i @koa&#x2F;router</p>
<p><strong>import koa from ‘koa’</strong></p>
<p><strong>import Router from ‘@koa&#x2F;router’</strong></p>
<p><strong>const app &#x3D; new koa()</strong></p>
<p><strong>const router &#x3D; new Router()</strong></p>
<p><strong>&#x2F;&#x2F;普通的get请求</strong></p>
<p><strong>router.get(‘&#x2F;‘,async ctx &#x3D;&gt; {</strong></p>
<p>​    ctx.body &#x3D; ‘Hello, Koa!’</p>
<p><strong>})</strong></p>
<p><strong>&#x2F;&#x2F;带请求参数的get请求 如<a target="_blank" rel="noopener" href="http://localhost:3000/user?id=1&&name=zhangsan">http://localhost:3000/user?id=1&amp;&amp;name=zhangsan</a></strong></p>
<p><strong>router.get(‘&#x2F;user’,async ctx &#x3D;&gt; {</strong></p>
<p>​    let {id,name} &#x3D; ctx.query</p>
<p>​    ctx.body &#x3D; <code>User ID: $&#123;id&#125;, Name: $&#123;name&#125;</code></p>
<p><strong>})</strong></p>
<p><strong>&#x2F;&#x2F;带路径参数的get请求 如<a target="_blank" rel="noopener" href="http://localhost:3000/user/2/wangwu">http://localhost:3000/user/2/wangwu</a></strong></p>
<p><strong>router.get(‘&#x2F;user&#x2F;:id&#x2F;:name’,async ctx &#x3D;&gt; {</strong></p>
<p>​    let {id,name} &#x3D; ctx.params</p>
<p>​    ctx.body &#x3D; <code>User ID: $&#123;id&#125;, Name: $&#123;name&#125;</code></p>
<p><strong>})</strong></p>
<p><strong>&#x2F;&#x2F;重定向</strong></p>
<p><strong>router.redirect(‘&#x2F;test’,’&#x2F;‘)</strong></p>
<p><strong>&#x2F;&#x2F;使用路由中间件</strong></p>
<p><strong>app.use(router.routes())</strong></p>
<p><strong>&#x2F;&#x2F;路由分组</strong></p>
<p><strong>const userRouter &#x3D; new Router({prefix:’&#x2F;user’})</strong></p>
<p><strong>userRouter.get(‘&#x2F;‘,async ctx &#x3D;&gt; {</strong></p>
<p>​    ctx.body &#x3D; ‘User List’</p>
<p><strong>})</strong></p>
<p><strong>userRouter.get(‘&#x2F;add’,async ctx &#x3D;&gt; {</strong></p>
<p>​    ctx.body &#x3D; ‘添加用户’</p>
<p><strong>})</strong></p>
<p><strong>userRouter.get(‘&#x2F;delete’,async ctx &#x3D;&gt; {</strong></p>
<p>​    ctx.body &#x3D; ‘删除用户’</p>
<p><strong>})</strong></p>
<p><strong>app.use(userRouter.routes())</strong></p>
<p><strong>app.listen(3000,()&#x3D;&gt;{</strong></p>
<p>​    console.log(‘服务器运行在 <a target="_blank" rel="noopener" href="http://localhost:3000/">http://localhost:3000</a>‘)</p>
<p><strong>})</strong></p>
<h2 id="解决post请求"><a href="#解决post请求" class="headerlink" title="解决post请求"></a>解决post请求</h2><p>前面都是解决一些get请求，但在平常我们肯定会遇到post请求，接下来我们就来解决一下，首先安装插件 npm i @koa&#x2F;bodyparser，用来解析post请求中以json和url格式发送的数据</p>
<p><strong>import bodyparser from ‘@koa&#x2F;bodyparser’</strong></p>
<p><strong>app.use(bodyparser())</strong></p>
<p><strong>router.post(‘&#x2F;user’,async ctx &#x3D;&gt;{</strong></p>
<p>​    console.log(ctx.request.body) &#x2F;&#x2F; 打印请求体</p>
<p>​    let {id,name} &#x3D; ctx.request.body</p>
<p>​    ctx.body &#x3D; <code>User ID: $&#123;id&#125;, Name: $&#123;name&#125;</code></p>
<p><strong>})</strong></p>
<h2 id="错误处理和设置跨域"><a href="#错误处理和设置跨域" class="headerlink" title="错误处理和设置跨域"></a>错误处理和设置跨域</h2><p>根据中间件的执行顺序，我们可以设置一个错误处理中间件用于解决在后续中间件中遇到问题时该怎么做，随便把跨域问题也讲了，当你想从你的服务器网址访问另一个网址时，浏览器有时会拦截这次请求，这时就要在服务器中设置允许跨域</p>
<p><strong>import cors from ‘@koa&#x2F;cors’</strong></p>
<p><strong>app.use(cors())</strong></p>
<p><strong>app.use(async (ctx,next)&#x3D;&gt;{</strong></p>
<p>​    try{</p>
<p>​        await next() &#x2F;&#x2F; 调用下一个中间件</p>
<p>​    }catch(err){</p>
<p>​        ctx.status &#x3D; 500</p>
<p>​        ctx.body &#x3D; ‘Internal Server Error’</p>
<p>​    }</p>
<p><strong>})</strong></p>
<h2 id="图片上传"><a href="#图片上传" class="headerlink" title="图片上传"></a>图片上传</h2><p>安装： npm i @koa&#x2F;multer</p>
<p><strong>import Multer from ‘@koa&#x2F;multer’</strong></p>
<p><strong>import path from ‘path’</strong></p>
<p><strong>&#x2F;&#x2F;配置磁盘存储</strong></p>
<p><strong>const storage &#x3D; Multer.diskStorage({</strong></p>
<p>​    destination:(req,file,callback)&#x3D;&gt;{</p>
<p>​        callback(null,’.&#x2F;upload’) &#x2F;&#x2F;指定上传文件的目录</p>
<p>​    },</p>
<p>​    filename:(req,file,callback)&#x3D;&gt;{</p>
<p>​        callback(null,Date.now() + path.extname(file.originalname)) &#x2F;&#x2F;指定上传文件的名称</p>
<p>​    }</p>
<p><strong>})</strong></p>
<p><strong>const multer &#x3D; Multer({&#x2F;&#x2F;实例化Multer</strong></p>
<p>​    storage,</p>
<p>​    fileFilter:(req,file,callback)&#x3D;&gt;{</p>
<p>​        if(file.mimetype.startsWith(‘image&#x2F;‘)){ &#x2F;&#x2F;只允许上传图片文件</p>
<p>​            callback(null,true)</p>
<p>​        }else{</p>
<p>​            callback(new Error(‘Only images are allowed’))</p>
<p>​        }</p>
<p>​    }</p>
<p><strong>})</strong></p>
<p><strong>router.post(‘&#x2F;upload’,multer.single(‘file’),async ctx &#x3D;&gt;{</strong></p>
<p>​    let file &#x3D; ctx.request.file</p>
<p>​    if(file){</p>
<p>​        console.log(file) &#x2F;&#x2F; 打印上传的文件信息</p>
<p>​        ctx.body &#x3D; <code>File uploaded successfully: $&#123;file.filename&#125;</code></p>
<p>​    }</p>
<p><strong>})</strong></p>
<h2 id="设置cookie、session和jwt"><a href="#设置cookie、session和jwt" class="headerlink" title="设置cookie、session和jwt"></a>设置cookie、session和jwt</h2><p>首先是cookie，cookie很简单在ctx中就能设置</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br></pre></td><td class="code"><pre><span class="line">router.get(&#x27;/&#x27;, async ctx =&gt; &#123;</span><br><span class="line">    //赋值</span><br><span class="line">    ctx.cookies.set(&quot;name&quot;,encodeURIComponent(&quot;陆豪&quot;)) //encodeURIComponent:url编码</span><br><span class="line">    ctx.cookies.set(&quot;web&quot;,&quot;baidu.com&quot;,&#123;</span><br><span class="line">        //30秒 [maxAge:有效期 单位:毫秒]</span><br><span class="line">        maxAge: 30 * 1000,</span><br><span class="line">        //httpOnly默认为true 可以防止跨站脚本攻击(XSS)、减少跨站请求伪造(CSRF)</span><br><span class="line">        httpOnly: false //允许浏览器通过js访问和修改该cookie</span><br><span class="line">    &#125;)</span><br><span class="line"></span><br><span class="line">    //取值 - 在同一个请求内, 无法立即获取到刚刚设置的cookie的值</span><br><span class="line">    let name = ctx.cookies.get(&quot;name&quot;)</span><br><span class="line">    console.log(&quot;name:&quot;,decodeURIComponent(name)) //decodeURIComponent:url解码</span><br><span class="line"></span><br><span class="line">    //删除</span><br><span class="line">    //ctx.cookies.set(&quot;name&quot;,&quot;&quot;,&#123;maxAge: 0&#125;)</span><br><span class="line"></span><br><span class="line">    ctx.body = &quot;dengruicode.com&quot;</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>接下来是session，它需要先安装：npm i koa-session</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br></pre></td><td class="code"><pre><span class="line">//koa-session 默认将 session 数据存储在客户端的 cookie 中</span><br><span class="line">app.keys = [&#x27;itlh&#x27;] //设置会话签名的密钥</span><br><span class="line">const CONFIG = &#123;</span><br><span class="line">    key: &#x27;DR&#x27;,  //存储在 cookie 中的键名</span><br><span class="line">    maxAge:  24 * 60 * 60 * 1000,  //24小时 有效期(单位:毫秒)</span><br><span class="line">    signed: true,  //是否启用会话签名, 用于防止CSRF攻击</span><br><span class="line">    secure: false,  //是否仅通过 https 协议发送 cookie</span><br><span class="line">&#125;</span><br><span class="line">app.use(Session(CONFIG, app))</span><br></pre></td></tr></table></figure>

<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br></pre></td><td class="code"><pre><span class="line">router.get(&#x27;/&#x27;, async ctx =&gt; &#123;</span><br><span class="line">    //赋值</span><br><span class="line">    ctx.session.name = &quot;陆豪&quot;</span><br><span class="line">    ctx.session.url = &quot;baidu.com&quot;</span><br><span class="line">    if(!ctx.session.user)&#123;</span><br><span class="line">        ctx.session.user = 100</span><br><span class="line">    &#125;else&#123;</span><br><span class="line">        ctx.session.user++</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    //取值</span><br><span class="line">    let name = ctx.session.name</span><br><span class="line">    console.log(&quot;name:&quot;,name)</span><br><span class="line"></span><br><span class="line">    //删除</span><br><span class="line">    //ctx.session = null //清空</span><br><span class="line">    //delete ctx.session.name //删除 session 中的 name 属性</span><br><span class="line"></span><br><span class="line">    ctx.body = &quot;用户:&quot; + ctx.session.user</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>

<p>最后是最高级也是最复杂的jwt，jwt是基于令牌（Token）的认证和授权机制，由头部、负载和签名组成</p>
<figure class="highlight plaintext"><table><tr><td class="gutter"><pre><span class="line">1</span><br><span class="line">2</span><br><span class="line">3</span><br><span class="line">4</span><br><span class="line">5</span><br><span class="line">6</span><br><span class="line">7</span><br><span class="line">8</span><br><span class="line">9</span><br><span class="line">10</span><br><span class="line">11</span><br><span class="line">12</span><br><span class="line">13</span><br><span class="line">14</span><br><span class="line">15</span><br><span class="line">16</span><br><span class="line">17</span><br><span class="line">18</span><br><span class="line">19</span><br><span class="line">20</span><br><span class="line">21</span><br><span class="line">22</span><br><span class="line">23</span><br><span class="line">24</span><br><span class="line">25</span><br><span class="line">26</span><br><span class="line">27</span><br><span class="line">28</span><br><span class="line">29</span><br><span class="line">30</span><br><span class="line">31</span><br><span class="line">32</span><br><span class="line">33</span><br><span class="line">34</span><br><span class="line">35</span><br><span class="line">36</span><br><span class="line">37</span><br><span class="line">38</span><br><span class="line">39</span><br><span class="line">40</span><br><span class="line">41</span><br><span class="line">42</span><br><span class="line">43</span><br><span class="line">44</span><br><span class="line">45</span><br><span class="line">46</span><br><span class="line">47</span><br><span class="line">48</span><br><span class="line">49</span><br><span class="line">50</span><br><span class="line">51</span><br><span class="line">52</span><br><span class="line">53</span><br><span class="line">54</span><br><span class="line">55</span><br></pre></td><td class="code"><pre><span class="line">import Koa from &#x27;koa&#x27;</span><br><span class="line">import Router from &#x27;@koa/router&#x27;</span><br><span class="line">import JWT from &#x27;jsonwebtoken&#x27;</span><br><span class="line"></span><br><span class="line">const hostname = &quot;127.0.0.1&quot;</span><br><span class="line">const port = 8008</span><br><span class="line"></span><br><span class="line">const app = new Koa()</span><br><span class="line">const router = new Router() //实例化一个 Router 对象</span><br><span class="line"></span><br><span class="line">router.get(&#x27;/&#x27;, async ctx =&gt; &#123;</span><br><span class="line">    let key = &#x27;koaTest&#x27; //密钥</span><br><span class="line">    let token = generateToken(key) //生成token</span><br><span class="line"></span><br><span class="line">    parseToken(token, key) //解析token</span><br><span class="line"></span><br><span class="line">    ctx.body = token</span><br><span class="line">&#125;)</span><br><span class="line"></span><br><span class="line">app.use(router.routes()) //将定义在 router 对象中的路由规则添加到 app 实例中</span><br><span class="line"></span><br><span class="line">//生成token</span><br><span class="line">let generateToken = key =&gt; &#123;</span><br><span class="line">    let id = 1 //用户唯一id</span><br><span class="line">    let now = Math.floor(Date.now() / 1000) //当前时间戳 单位:秒</span><br><span class="line">    let expire = 24 * 60 * 60</span><br><span class="line"></span><br><span class="line">    //负载</span><br><span class="line">    let payload = &#123;</span><br><span class="line">        sub: id, //Subject 主题 (用户唯一id)</span><br><span class="line">        iss: &#x27;dengruicode.com&#x27;, //Issuer 发行者</span><br><span class="line">        iat: now, //Issued At 发行时间</span><br><span class="line">        nbf: now, //Not Before 生效时间</span><br><span class="line">        exp: now + expire, //Expiration Time 过期时间</span><br><span class="line">        aud: [&#x27;&#x27;], //Audience 观众字段为空,表示没有观众限制,可以被任何接收方处理</span><br><span class="line">        data: &#123; //自定义数据</span><br><span class="line">            name: &#x27;陆豪&#x27;,</span><br><span class="line">            gender: &#x27;男&#x27;,</span><br><span class="line">        &#125;</span><br><span class="line">    &#125;</span><br><span class="line"></span><br><span class="line">    //使用负载(payload)、密钥(key)和指定的签名算法(HS256)生成token</span><br><span class="line">    let token = JWT.sign(payload, key, &#123; algorithm: &#x27;HS256&#x27; &#125;)</span><br><span class="line">    return token</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">//解析token</span><br><span class="line">let parseToken = (token, key) =&gt; &#123;</span><br><span class="line">    let payload = JWT.verify(token, key, &#123; algorithm: &#x27;HS256&#x27; &#125;)</span><br><span class="line">    console.log(&#x27;解析后的payload:&#x27;, payload)</span><br><span class="line">&#125;</span><br><span class="line"></span><br><span class="line">app.listen(port, hostname, () =&gt; &#123;</span><br><span class="line">    console.log(`服务器已启动: http://$&#123;hostname&#125;:$&#123;port&#125;`)</span><br><span class="line">&#125;)</span><br></pre></td></tr></table></figure>
      
    </div>
    <footer class="article-footer">
      <a data-url="https://lhaik.gitcode.host/2025/06/06/koa2%E7%9A%84%E5%AD%A6%E4%B9%A0/" data-id="cmbqcgbjm0000nsg6e4y575s6" data-title="koa2的学习" class="article-share-link"><span class="fa fa-share">分享</span></a>
      
      
      
    </footer>
  </div>
  
</article>



  


</section>
        
          <aside id="sidebar">
  
    

  
    

  
    
  
    
  <div class="widget-wrap">
    <h3 class="widget-title">归档</h3>
    <div class="widget">
      <ul class="archive-list"><li class="archive-list-item"><a class="archive-list-link" href="/archives/2025/06/">六月 2025</a></li></ul>
    </div>
  </div>


  
    
  <div class="widget-wrap">
    <h3 class="widget-title">最新文章</h3>
    <div class="widget">
      <ul>
        
          <li>
            <a href="/2025/06/09/%E4%B8%80%E4%BA%9B%E6%9C%80%E8%BF%91%E5%86%99%E6%AF%94%E8%B5%9B%E9%A1%B9%E7%9B%AE%E7%9A%84%E5%BF%83%E5%BE%97/">一些最近写比赛项目的心得</a>
          </li>
        
          <li>
            <a href="/2025/06/06/koa2%E7%9A%84%E5%AD%A6%E4%B9%A0/">koa2的学习</a>
          </li>
        
      </ul>
    </div>
  </div>

  
</aside>
        
      </div>
      <footer id="footer">
  
  <div class="outer">
    <div id="footer-info" class="inner">
      
      &copy; 2025 lhaik<br>
      Powered by <a href="https://hexo.io/" target="_blank">Hexo</a>
    </div>
  </div>
</footer>

    </div>
    <nav id="mobile-nav">
  
    <a href="/" class="mobile-nav-link">Home</a>
  
    <a href="/archives" class="mobile-nav-link">Archives</a>
  
</nav>
    


<script src="/js/jquery-3.6.4.min.js"></script>



  
<script src="/fancybox/jquery.fancybox.min.js"></script>




<script src="/js/script.js"></script>





  </div>
</body>
</html>